package org.robot.scm.platform;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.robot.scm.pojos.config.base.BasePlatform;
import org.robot.scm.pojos.config.base.BaseSchedule;
import org.robot.scm.pojos.enums.PlatformEnum;
import org.robot.scm.utils.StreamUtils;

/**
 * 定时任务
 *
 * @Author : Awn create on 2024/6/6 15:12
 */
@Slf4j
public abstract class AbstractSchedule {

    @Getter
    private static final List<? extends AbstractSchedule> registries = ReflectionLoader.load(AbstractSchedule.class);

    protected static ScheduledExecutorService executor = Executors.newScheduledThreadPool(registries.size());

    public static void start() {
        if (!AbstractMonitor.mainConfig.getEnables().contains(PlatformEnum.SCHEDULE.getVal())) {
            return;
        }
        log.info("schedule started ... ok");
        registries.forEach(registry -> {
            BaseSchedule config = registry.cronConfig();
            if (Objects.isNull(config)) {
                return;
            }
            LocalTime targetTime = LocalTime.of(config.hour(), config.minute());
            long now = System.currentTimeMillis();
            long targetMillis = LocalDateTime.now().with(targetTime).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

            // 如果已经过了今天的目标时间，则推迟到明天
            if (now > targetMillis) {
                targetMillis += TimeUnit.DAYS.toMillis(1);
            }
            long initialDelay = targetMillis - now;
            executor.scheduleAtFixedRate(registry::handle, initialDelay, TimeUnit.DAYS.toMillis(1), TimeUnit.MILLISECONDS);
        });
    }

    public abstract void handle();

    public abstract String getName();

    public BaseSchedule cronConfig() {
        BasePlatform platform = AbstractMonitor.mainConfig.getPlatform(PlatformEnum.SCHEDULE);
        List<BaseSchedule> cronConfig = platform.getCronConfig();
        return StreamUtils.filterOne(cronConfig, item -> item.getJobName().equals(getName()));
    }
}
